const express = require('express')
const fs = require('fs')
const WechatPay = require('../wechatpay-nodejs-sdk')
const router = express.Router()
const logger = require('../logger')
const Product = require('../models/Product')
const Order = require('../models/Order')
const { ORDER_STATUS } = require('../constants')
const { WECHAT_APP_ID, WECHAT_MCH_ID, WECHAT_NOTIFY_URL, SECRET_KEY } = require('../config')

const wechatPay = new WechatPay({
  appid: WECHAT_APP_ID, // 应用ID
  mchid: WECHAT_MCH_ID, // 商户ID
  publicKey: fs.readFileSync('./apiclient_cert.pem'), // 商户公钥
  privateKey: fs.readFileSync('./apiclient_key.pem'), // 商户的私钥
  secretKey: SECRET_KEY // V3秘钥
})

async function createOrder(productId) {
  // 1.检查商品Id是否正确
  const product = await Product.findById(productId)
  if (!product) {
    throw new Error("Product not found")
  }
  // 2.生成订单信息
  const newOrder = new Order({
    product: productId,
    totalFee: product.price,
    orderStatus: ORDER_STATUS.UN_PAID
  })
  await newOrder.save()

  return {
    product,
    newOrder
  }
}

/** 统一调用下单接口方法 */
async function invokeNativePay(newOrder, product, req) {
  const result = await wechatPay.transactions_native({
    description: `${product.name}`, // 商品描述
    out_trade_no: newOrder.id, // 商户订单号
    notify_url: WECHAT_NOTIFY_URL, // 通知地址
    amount: {
      total: product.price, // 订单金额
      currency: 'CNY' // 货币类型
    },
    scene_info: {
      payer_client_ip: req.ip // 客户端Ip
    }
  })
  logger.info(`统一下单接口:${JSON.stringify(result)}}`)
  const { code_url } = result
  /** 更新订单信息 */
  await Order.findByIdAndUpdate(newOrder.id, { code_url })
  return code_url
}

/**
 * Native 支付
 */
router.get('/native/:productId', async (req, res) => {
  try {
    // 1.生成订单
    const { productId } = req.params
    const { product, newOrder } = await createOrder(productId)
    // 调用微信统一下单接口得到code_url
    const code_url = await invokeNativePay(newOrder, product, req)
    // 反回数据
    res.send({ orderNo: newOrder.id, code_url })

  } catch (err) {
    logger.error("Native Error:", err)
    res.status(500).send("Native Internal Server Error")
  }
})

/**
 * 微信支付回调接口通知
 */
router.post('/notify', async (req, res) => {
  try {
    const { headers, body } = req
    // 应答时间撮
    const signature = headers['wechatpay-signature'];
    logger.info('signature', signature)
    //Wechatpay-Serial 微信服务器平台的证书序列号
    const serial = headers['wechatpay-serial'];
    logger.info('serial', serial)
    //HTTP 头 Wechatpay-Timestamp 中的应答时间戳
    const timestamp = headers['wechatpay-timestamp'];
    logger.info('timestamp', timestamp)
    //HTTP 头 Wechatpay-Nonce 中的应答随机串
    const nonce = headers['wechatpay-nonce'];
    logger.info('nonce', nonce)
    // 验证签名
    const verifyResult = await wechatPay.verifySign({
      body,//请求主体
      signature,//微信服务器发过来的签名
      serial,//证书序列号
      nonce,//随机字符串
      timestamp//时间戳
    })
    //如果事件类型是TRANSACTION.SUCCESS说明交易成功，说明用户支付成功
    if (verifyResult && body && body.event_type === "TRANSACTION.SUCCESS") {
      // 解密应答资源数据
      const resultStr = wechatPay.decrypt(body.resource)
      const result = JSON.parse(resultStr)
      // 更新订单数据.out_trade_no
      await Order.findByIdAndUpdate(result.out_trade_no, { orderStatus: ORDER_STATUS.PAID, })
      res.send(200).send({ code: "SUCCESS", message: "支付成功" })
    } else {
      res.send(200).send({ code: "FAIL", message: "支付失败" })
    }
  } catch (error) {
    res.status(500).send("Notify Internal Server Error:" + + error.message)
  }
})


/** 轮训订单接口 */
router.get('/order/:orderNo', async (req, res) => {
  try {
    const { orderNo } = req.params;
    const result = await wechatPay.query({ out_trade_no: orderNo });
    logger.info(`wechatPay.query.result: ${JSON.stringify(result)}`);
    await Order.findByIdAndUpdate(orderNo, {
      orderStatus: result.trade_state === 'SUCCESS' ? ORDER_STATUS.PAID : ORDER_STATUS.UN_PAID
    })
    res.status(200).send(result);
  } catch (err) {
    res.status(500).send('Error querying transaction');
  }
})

/** 取消订单 */
router.get('/order/:orderNo/close', async (req, res) => {
  try {
    const { orderNo } = req.params;
    await wechatPay.close({ out_trade_no: orderNo })
    await Order.findByIdAndUpdate(orderNo, {
      orderStatus: ORDER_STATUS.CLOSE_PID
    })
    res.send({ message: "Order Successfully Closed" })
  } catch (err) {
    logger.error('Error closing transaction', err)
    res.status(500).send('Error closing transaction')
  }
})
module.exports = router